// 定义一个数字类型的数组
let numbers: number[] = [1, 3, 5]
// 也可以使用这种方式，是一个泛型的格式
let number: Array<string> = ['1', '3', '5']
// 联合类型 使用符号 |
let arr: (number | string)[] = [1, '3', 5]

// 类型别名 type
type CustomArray = (number | string)[]
let arr1: CustomArray = [1, '3', 5]

// 函数的类型
// 如果函数没有返回值就可以直接定义成void类型
function add(num1: number, num2: number): number {
  return num1 + num2
}
// 注意这两个的写法就不一样，一个是直接function另一个是使用const创建
const add2 = (num1: number, num2: number): number => {
  return num1 + num2
}

type person3 = {
  name: string
  say(): void
}

let per: person3 = {
  name: 'jack',
  say() {

  },
}

// 接口interface 只能用于指定对象，类型别名什么都可以
interface IPerson {
  name: string
  sayHi(): void
}

let person: IPerson = {
  name: 'tom',
  sayHi() { }
}

// 接口可以继承 extends
interface IPerson2 extends IPerson {
  age: number
}

let person2: IPerson2 = {
  age: 12,
  name: 'jim',
  sayHi() { }
}

// 元组 是一个单独类型的数组，它明确知道包含有多少个元素，以及每个索引对应的类型
let position: [number, string] = [13, 'tom']

// 字面量类型，注意这里的str2就是字面量类型
let str1 = 'Hello TS'
const str2 = 'Hello TS'

// 一般使用字面量类型配合联合类型，来表示只能输入限制的固定的几个参数
// 例如贪吃蛇中的上下左右
function changeDirection(direction: 'up' | 'down' | 'left' | 'right') {
  // ts文件运行是打印会报错，参考文献：https://blog.csdn.net/weixin_50336155/article/details/120345624
  // 禁止系统上运行脚本的报错，参考文献： https://blog.csdn.net/dujyong/article/details/106359483
  console.log(direction)
}

// changeDirection('up')

// 枚举 enum 明确一组可选值，类似于字面量类型和联合类型组合的功能
// 如果不给枚举的项目传值，他会默认是数字，如果传值，则会是具体的值
enum Direction {
  Up = 'Up',
  Down = '2',
  Left = 'Left',
  Right = 3
}

function changeDirection2(direction: Direction) {
  console.log(direction)
}

// changeDirection2(Direction.Left)

// typeof的作用 它主要是为了获取数据的类型
// 在ts中typeof可以在类型上下文中引用变量或属性的类型（功能类似于类型查询）
// 使用场景：根据已有变量的值，获取改值的类型，来简化类型书写
console.log(typeof str1) // string
console.log(typeof str2) // string

let p = {
  name: 'tom',
  age: 18
}

// 这里直接使用已有的数据p的类型来定义了函数formatPoint的参数类型
// 至于p的类型，则是由ts根据类型推论得出来的
function formatPoint(point: typeof p) {
  console.log(point)
}
// formatPoint({ name: '张三', age: 16 })
